/*******************************************************************************
 * Copyright (c) 2013 Michele Nanna.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Public License v3.0
 * which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/gpl.html
 * 
 * Contributors:
 *     https://gitorious.org/provinciawifi - initial API and implementation
 *     Michele Nanna - fix some issues
 ******************************************************************************/
package com.systemfastforward.provinciawifi.service;

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.params.ClientPNames;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Handler;
import android.os.IBinder;
import android.preference.PreferenceManager;
import android.text.TextUtils;

import com.systemfastforward.provinciawifi.AutoLoginServicePreferenceActivity;
import com.systemfastforward.provinciawifi.R;

/**
 * Perform an auto login on Provincia WiFi network, after connection on access
 * point.
 * 
 * @author https://gitorious.org/provinciawifi
 * 
 */
public class WifiAuthenticatorService extends Service {

	private static final int NOTIFICATION_NO_CREDENTIALS = 1;
	private static final int NOTIFICATION_STATUS = 1;

	private static final String FORM_URI = "https://captiveportal.provinciawifi.it:8001/";
	private static final String PARAM_VALUE_ACCEPT = "Accedi+al+servizio";
	private static final String PARAM_VALUE_REDIRURL = "http://www.google.com/";

	final Handler mHandler = new Handler();

	@Override
	public void onStart(Intent intent, int startId) {
		handleIntent(intent);
	}

	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		handleIntent(intent);
		return Service.START_NOT_STICKY;
	}

	private void handleIntent(Intent intent) {
		(new AuthThread()).start();
	}

	@Override
	public IBinder onBind(Intent intent) {
		return null;
	}

	public class AuthThread extends Thread {
		@SuppressWarnings("deprecation")
		public void run() {
			// request http login
			HttpParams httpParameters = new BasicHttpParams();
			HttpConnectionParams.setConnectionTimeout(httpParameters, 10000);
			HttpConnectionParams.setSoTimeout(httpParameters, 10000);
			HttpClient httpclient = new DefaultHttpClient(httpParameters);
			HttpPost httppost = new HttpPost(FORM_URI);

			try {
				SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(WifiAuthenticatorService.this);
				String username = prefs.getString("username", null);
				String password = prefs.getString("password", null);
				Context context = WifiAuthenticatorService.this;

				// login data not set or invalid -- launch preferences dialog
				if (TextUtils.isEmpty(username) || TextUtils.isEmpty(password)) {

					NotificationManager nm = (NotificationManager) context.getSystemService(NOTIFICATION_SERVICE);
					CharSequence txt = context.getText(R.string.msg_not_insert_credentials);
					Notification n = new Notification(R.drawable.ic_stat_provinciawifi, txt, 0);

					Intent notificationIntent = new Intent(context, AutoLoginServicePreferenceActivity.class);
					notificationIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
					PendingIntent contentIntent = PendingIntent.getActivity(context, 0, notificationIntent, 0);
					n.flags += Notification.FLAG_AUTO_CANCEL;
					n.setLatestEventInfo(context, context.getText(R.string.app_name), context.getText(R.string.msg_insert_credentials), contentIntent);

					nm.notify(NOTIFICATION_NO_CREDENTIALS, n);
					return;
				}

				// POST data
				List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(4);
				nameValuePairs.add(new BasicNameValuePair("auth_user", username));
				nameValuePairs.add(new BasicNameValuePair("auth_pass", password));
				nameValuePairs.add(new BasicNameValuePair("accept", PARAM_VALUE_ACCEPT));
				nameValuePairs.add(new BasicNameValuePair("redirurl", PARAM_VALUE_REDIRURL));
				httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));

				// connection parameters
				httpclient.getParams().setBooleanParameter(ClientPNames.HANDLE_REDIRECTS, false);
				httpclient.getParams().setBooleanParameter("http.protocol.expect-continue", false);

				// execute request
				HttpResponse response = httpclient.execute(httppost);
				if (response.getStatusLine().getStatusCode() != 200)
					throw new Exception();

				Scanner sc = new Scanner(response.getEntity().getContent());
				if (sc.findWithinHorizon("\\Q" + PARAM_VALUE_REDIRURL + "\\E", 0) == null)
					throw new Exception();

				postStatusBarNotification(WifiAuthenticatorService.this, R.string.msg_logged_in);
			}

			catch (Exception e) {
				postStatusBarNotification(WifiAuthenticatorService.this, R.string.msg_login_error);
			}

		}

		@SuppressWarnings("deprecation")
		private void postStatusBarNotification(Context ctx, int textStringId) {
			NotificationManager nm = (NotificationManager) ctx.getSystemService(NOTIFICATION_SERVICE);
			CharSequence txt = WifiAuthenticatorService.this.getText(textStringId);
			Notification n = new Notification(R.drawable.ic_stat_provinciawifi, txt, 0);
			n.flags += Notification.FLAG_AUTO_CANCEL;
			n.setLatestEventInfo(ctx, ctx.getText(R.string.app_name), ctx.getText(textStringId), PendingIntent.getActivity(ctx, 0, new Intent(), 0));
			nm.notify(NOTIFICATION_STATUS, n);
		}
	}
}
